import cv2 as cv
import cv2.face
from PIL import Image
import os
import numpy as np
from cap import cap as cp

# 获得面部信息
def get_face_info(name):
    # 创建文件夹
    # path = '../images/' + name
    path = get_train_name('../images/')
    os.mkdir(path)
    # 开启摄像头
    num = 0  # 照片编号，需要录入一定的样本量
    cap = cp
    # cap = cv.VideoCapture(0)
    # 加载分类器
    face_detect = cv.CascadeClassifier(
        '../haarcascade_frontalface_default.xml')
    while cap.isOpened():
        flag, ima = cap.read()
        if not flag:
            break
        gray_img = cv.cvtColor(ima, cv.COLOR_BGR2GRAY)
        face = face_detect.detectMultiScale(gray_img, scaleFactor=1.2, minNeighbors=4)
        # 对检测出的图像进行画框
        for x, y, w, h in face:
            cv.rectangle(ima, (x, y), (x + w, y + h), color=(0, 0, 255), thickness=1)
        cv.imshow('title', ima)
        if ord('s') == cv.waitKey(16):
            pathname = path + '/' + str(num) + '.jpg'
            num += 1
            cv.imwrite(pathname, ima)
            if num == 25:
                # cap.release()
                cv.destroyAllWindows()
                break
        else:
            continue

    return path


# 参数label用来表示不同的人
# path 是对目录path下的照片进行训练
def tran_image(path, labelx):
    id_contain = []
    face_contain = []
    # 加载分类器
    face_detect = cv.CascadeClassifier(
        'haarcascade_frontalface_default.xml')
    # 得到path目录下的所有文件名
    dirs = os.listdir(path)
    image_paths = [path + '/' + a for a in dirs]
    for imagePath in image_paths:
        # 打开图片并灰度化
        pil_img = Image.open(imagePath).convert('L')
        # 将图片转为数组
        img_np = np.array(pil_img, 'uint8')
        # 获得人脸特征, 分类图提取人脸
        # 因为这里我采集的同一人的人脸， 因此id相同
        faces = face_detect.detectMultiScale(img_np, scaleFactor=1.2, minNeighbors=5)
        for x, y, w, h in faces:
            id_contain.append(labelx)
            face_contain.append(img_np[y:y + h, x:x + w])
            # 训练时显示训练照片
            # 这一步可以省略
            # m = cv.imread(imagePath)
            # cv.rectangle(m, (x, y), (x + w, y + h), color=(0, 0, 255), thickness=1)
            # cv.imshow('12', m)
            # cv.waitKey(100)
    # 加载识别器
    recognizer = cv2.face.LBPHFaceRecognizer_create()
    # 对得到的人脸进行训练
    recognizer.train(face_contain, np.array(id_contain))
    # 将训练好的数据写入到trains文件夹下
    # recognizer.write(get_train_name('../trains/'))
    recognizer.write('../trains/' + str(labelx))


# 获得训练后数据文件的名字，注意，必须要存在trains文件夹，而且trains文件夹必须和此文件的父目录平级
def get_train_name(p):
    # path = '../trains/'
    path = p
    listdir = os.listdir(path)
    nums = []
    for name in listdir:
        num = name.split('.')[0]
        nums.append(int(num))
    nums.sort()
    if len(listdir) != 0:
        # return path + str(nums[-1] + 1) + '.yml'
        return path + str(nums[-1] + 1)
    else:
        # return path + '1' + '.yml'
        return path + '1'


# 对单张图像进行验证
def verify1(image1):
    # 将照片灰度化
    gray_image1 = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY)
    # 加载分类器
    face_detect = cv.CascadeClassifier(
        'haarcascade_frontalface_default.xml')
    # 获得这张照片上的人脸数据
    face = face_detect.detectMultiScale(gray_image1)
    for file in os.listdir("../trains/"):
        # 加载识别器
        recogizer = cv.face.LBPHFaceRecognizer_create()
        # 加载数据
        recogizer.read('../trains/' + file)
        # 对照片进行评估
        for x, y, w, h in face:
            ids, confidence = recogizer.predict(gray_image1[y:y + h, x:x + w])
            print(confidence)
            if confidence < 60:
                print(ids, confidence, sep=" ")
                # cv.rectangle(gray_image1, (x, y), (x + w, y + h), color=(0, 0, 255), thickness=1)
                # cv.imshow('123', gray_image1)
                # print(x, y, w, h)
                # cv.waitKey(2000)
                # cv.destroyAllWindows()
                return True, ids
    return False, -1
